// 文件名：batched_logger.cpp
// 目的：实现一个批量写入的简单日志器（BatchedLogger），将多条日志先缓存在内存中，
//      达到批量阈值后统一刷写到文件，减少频繁 I/O 的开销。
// 设计要点：
//   - 使用 std::vector<LogEntry> 作为缓冲池，入队 O(1) 摊还时间；
//   - 通过 batchSize_ 控制批量大小；达到阈值自动 flush()；
//   - 文件以追加模式（std::ios::app）打开，确保不会截断已有日志；
//   - flush() 逐条写入并显式 file_.flush()，降低数据留在用户态缓冲的风险。
// 注意事项：
//   - 线程安全：本类非线程安全；多线程下需在外部加锁或使用并发安全队列/双缓冲策略；
//   - 异常与错误：未检查文件是否成功打开（file_.is_open()），实际工程中应检测并处理；
//   - 耐久性：std::ofstream::flush() 只保证用户态缓冲落到内核页缓存，不等同于落盘；
//             若需更强持久化语义，可在平台上调用 fsync/F_FULLFSYNC 等；
//   - 关闭时机：建议在析构函数中调用 flush()，避免程序退出前遗漏尾批日志（本示例未实现）；
//   - 日志格式：使用 CSV 风格 "timestamp,message"；若 message 含逗号/换行/引号，
//             应进行转义或改用更稳健的格式（JSON/行分隔/长度前缀等）。

#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cstdint>

// 单条日志项：消息与时间戳
// 说明：timestamp 的单位与来源（秒、毫秒、单调时钟/墙钟）由调用方约定；
//       若需跨系统一致性，建议采用 ISO-8601 文本或统一的 epoch 毫秒。
struct LogEntry {
    std::string message;
    std::uint64_t timestamp;
};

class BatchedLogger {
public:
    // 构造函数
    // 参数：
    //   batchSize —— 触发刷写的批量阈值（建议 > 0）；
    //   filePath  —— 日志文件路径，以追加模式打开。
    // 优化：预先 reserve batchSize_，减少缓冲区扩容次数。
    BatchedLogger(std::size_t batchSize, std::string filePath)
        : batchSize_(batchSize), file_(std::move(filePath), std::ios::app) {
        entries_.reserve(batchSize_);
        // 实际工程中可添加校验：
        // if (!file_.is_open()) { throw std::runtime_error("Failed to open log file"); }
    }

    // 追加一条日志；当累计条数达到 batchSize_ 时自动刷写
    // 复杂度：摊还 O(1)；当触发 flush() 时包含写盘成本
    void log(std::string message, std::uint64_t timestamp) {
        entries_.push_back(LogEntry{std::move(message), timestamp});
        if (entries_.size() >= batchSize_) {
            flush();
        }
    }

    // 将缓冲区内容写入文件并清空缓冲
    // 格式：timestamp,message\n
    // 注意：此处未做转义处理；若 message 可能包含逗号/换行/引号，请进行安全编码或转义。
    void flush() {
        for (const auto& entry : entries_) {
            file_ << entry.timestamp << "," << entry.message << '\n';
        }
        entries_.clear();   // 清空缓冲，保留容量
        file_.flush();      // 刷新到内核缓冲（非强持久化）
        // 如需更强语义，可在此处调用平台特定的 fsync(fileno) 或 F_FULLFSYNC（macOS）
    }

    // 建议（未实现）：
    // ~BatchedLogger() {
    //     // 析构时尝试刷写尾批，避免遗漏
    //     if (!entries_.empty()) flush();
    // }

private:
    std::size_t batchSize_;     // 触发刷写的批量阈值
    std::ofstream file_;        // 以追加模式打开的文件流
    std::vector<LogEntry> entries_; // 内存缓冲区（批量池）
};

int main() {
    // 示例：批量阈值为 3，日志文件为 "logs.txt"
    BatchedLogger logger(3, "logs.txt");

    // 写入三条日志，第 3 条将触发自动 flush()
    logger.log("system start", 1700000001);
    logger.log("user login", 1700000002);
    logger.log("cache warmed", 1700000003); // 触发 flush

    // 再写一条，此时缓冲区尚未满；可手动 flush 以确保落盘
    logger.log("periodic heartbeat", 1700000004);
    logger.flush(); // 手动 flush 余下日志

    std::cout << "Logs written to logs.txt\n";
    return 0;
}